package org.dtrd.modules.control.job;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchiveLaboratory;
import org.dtrd.modules.archive.service.IDtrdEntRdLaboratoryService;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTarget;
import org.dtrd.modules.control.entity.po.DtrdEntRdSigninTargetDetail;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetDetailService;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetService;
import org.dtrd.modules.record.entity.po.*;
import org.dtrd.modules.record.service.*;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 保存控制目标的实际值
 * @author qr
 * @date 2022/4/2 10:46
 */
@Component
public class SaveTargetValueJob implements Job {

    @Autowired
    private IDtrdEntRdSigninTargetService targetService;
    @Autowired
    private IDtrdEntRdSigninTargetDetailService targetDetailService;
    @Autowired
    private IHeightWeightRecordService heightWeightRecordService;
    @Autowired
    private IBloodPressureRecordService bloodPressureRecordService;
    @Autowired
    private IWaistlineRecordService waistlineRecordService;
    @Autowired
    private IMedicalRecordService medicalRecordService;
    @Autowired
    private ISugarRecordService sugarRecordService;
    @Autowired
    private IDtrdEntRdLaboratoryService laboratoryService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        List<DtrdEntRdSigninTarget> targets = targetService.getLatestTargets();
        List<Date> thisWeekDays = DateUtils.getWeekDate(new Date());
        if (CollectionUtil.isNotEmpty(targets)) {
            for (DtrdEntRdSigninTarget target : targets) {
                Integer targetId = target.getDataId();
                Integer patientId = target.getPatientId();
                // region 保存体重/bmi
                DtrdEntRdSigninHeightWeight bmiRecord = heightWeightRecordService.getHeightWeightRecordLatest(patientId);
                Optional.ofNullable(bmiRecord).ifPresent(r -> {
                    targetDetailService.saveTargetDetailRealValue(targetId, r.getHeightWeightBmi(), Constant.TargetProject.BMI.getType());
                    targetDetailService.saveTargetDetailRealValue(targetId, r.getHeightWeightWeight(), Constant.TargetProject.WEIGHT.getType());
                });
                // endregion
                // region 保存高压/低压/心率
                LambdaQueryWrapper<DtrdEntRdSigninBloodPressure> queryWrapper1 = Wrappers.lambdaQuery(DtrdEntRdSigninBloodPressure.class)
                        .eq(DtrdEntRdSigninBloodPressure::getPatientId, patientId)
                        .le(DtrdEntRdSigninBloodPressure::getRecordDate, thisWeekDays.get(6))
                        .ge(DtrdEntRdSigninBloodPressure::getRecordDate, thisWeekDays.get(0));
                List<DtrdEntRdSigninBloodPressure> bloodPressures = bloodPressureRecordService.list(queryWrapper1);
                if (CollectionUtil.isNotEmpty(bloodPressures)) {
                    // 高压
                    Double avgHigh = bloodPressures.stream()
                            .map(DtrdEntRdSigninBloodPressure::getBloodPressureHighPressure)
                            .filter(Objects::nonNull)
                            .collect(Collectors.averagingInt(ph -> ph));
                    targetDetailService.saveTargetDetailRealValue(targetId, decimalFormat(avgHigh), Constant.TargetProject.PRESSURE_HIGH.getType());
                    // 低压
                    Double avgLow = bloodPressures.stream()
                            .map(DtrdEntRdSigninBloodPressure::getBloodPressureLowVoltage)
                            .filter(Objects::nonNull)
                            .collect(Collectors.averagingInt(pl -> pl));
                    targetDetailService.saveTargetDetailRealValue(targetId, decimalFormat(avgLow), Constant.TargetProject.PRESSURE_LOW.getType());
                    // 心率
                    Double avgHeartRate = bloodPressures.stream()
                            .map(DtrdEntRdSigninBloodPressure::getBloodPressureHeartRate)
                            .filter(Objects::nonNull)
                            .collect(Collectors.averagingInt(hr -> hr));
                    targetDetailService.saveTargetDetailRealValue(targetId, decimalFormat(avgHeartRate), Constant.TargetProject.HEART_RATE.getType());
                }
                // endregion
                // region 腰围
                DtrdEntRdSigninWaistline waistRecord = waistlineRecordService.getWaistLineRecordLatestByPatientId(patientId);
                Optional.ofNullable(waistRecord).ifPresent(r -> targetDetailService.saveTargetDetailRealValue(targetId, Float.valueOf(r.getWaistlineValue()), Constant.TargetProject.WAIST.getType()));
                // endregion
                // region用药
                DtrdEntRdSigninMedicalRecord medicalRecord = medicalRecordService.getMedicalRecordLatestByPatientId(patientId);
                Optional.ofNullable(medicalRecord).ifPresent(r -> {
                    LambdaUpdateWrapper<DtrdEntRdSigninTargetDetail> updateWrapper = Wrappers.lambdaUpdate(DtrdEntRdSigninTargetDetail.class)
                            .eq(DtrdEntRdSigninTargetDetail::getPatientId, patientId)
                            .eq(DtrdEntRdSigninTargetDetail::getTargetId, targetId)
                            .eq(DtrdEntRdSigninTargetDetail::getProjectType, Constant.TargetProject.DRUG.getType())
                            .set(true, DtrdEntRdSigninTargetDetail::getRemark, r.getMedicalRecordDescribe());
                    targetDetailService.update(updateWrapper);
                });
                // endregion
                // region空腹血糖
                LambdaQueryWrapper<DtrdEntRdSigninSugarValue> queryWrapper2 = Wrappers.lambdaQuery(DtrdEntRdSigninSugarValue.class)
                        .eq(DtrdEntRdSigninSugarValue::getPatientId, patientId)
                        .eq(DtrdEntRdSigninSugarValue::getSugarValueTimeTypeId, Constant.SugarRecordType.BEFOREBREAKFAST.getType())
                        .le(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(6))
                        .ge(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(0));
                List<DtrdEntRdSigninSugarValue> sugarLimosisList = sugarRecordService.list(queryWrapper2);
                if (CollectionUtil.isNotEmpty(sugarLimosisList)) {
                    Double avgSugarLimosis = sugarLimosisList.stream()
                            .map(DtrdEntRdSigninSugarValue::getSugarValueSugarValue)
                            .filter(Objects::nonNull)
                            .collect(Collectors.averagingDouble(sl -> sl));
                    targetDetailService.saveTargetDetailRealValue(targetId, decimalFormat(avgSugarLimosis), Constant.TargetProject.FBG.getType());
                }
                DtrdEntRdSigninSugarValue limosisSugar = sugarRecordService.getSugarValueLatestByPatientIdAndType(patientId, Constant.SugarRecordType.BEFOREBREAKFAST.getType());
                // endregion
                // region餐后血糖
                LambdaQueryWrapper<DtrdEntRdSigninSugarValue> queryWrapper3 = Wrappers.lambdaQuery(DtrdEntRdSigninSugarValue.class)
                        .eq(DtrdEntRdSigninSugarValue::getPatientId, patientId)
                        .in(DtrdEntRdSigninSugarValue::getSugarValueTimeTypeId,
                                Constant.SugarRecordType.AFTERBREAKFAST.getType(),
                                Constant.SugarRecordType.AFTERLUNCH.getType(),
                                Constant.SugarRecordType.AFTERDINNER.getType())
                        .le(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(6))
                        .ge(DtrdEntRdSigninSugarValue::getRecordDate, thisWeekDays.get(0));
                List<DtrdEntRdSigninSugarValue> sugarAfterMealList = sugarRecordService.list(queryWrapper3);
                if (CollectionUtil.isNotEmpty(sugarAfterMealList)) {
                    Double avgSugarAfterMeal = sugarAfterMealList.stream()
                            .map(DtrdEntRdSigninSugarValue::getSugarValueSugarValue)
                            .filter(Objects::nonNull)
                            .collect(Collectors.averagingDouble(sam -> sam));
                    targetDetailService.saveTargetDetailRealValue(targetId, decimalFormat(avgSugarAfterMeal), Constant.TargetProject.PBG.getType());
                }
                // endregion
                //region 实验室检查的数据，有 血红蛋白(Hb1Ac) 总胆固醇(TC) 高密度脂蛋白(HDL) 低密度脂蛋白(LDL) 等数据
                DtrdEntRdArchiveLaboratory laboratory = laboratoryService.getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveLaboratory.class)
                        .eq(DtrdEntRdArchiveLaboratory::getPatientId, patientId));
                if (laboratory != null) {
                    targetDetailService.saveTargetDetailRealValue(targetId, laboratory.getHba1c(), Constant.TargetProject.HBA1C.getType());
                    targetDetailService.saveTargetDetailRealValue(targetId, laboratory.getTc(), Constant.TargetProject.TC.getType());
                    targetDetailService.saveTargetDetailRealValue(targetId, laboratory.getTg(), Constant.TargetProject.TG.getType());
                    targetDetailService.saveTargetDetailRealValue(targetId, laboratory.getHdlc(), Constant.TargetProject.HDL.getType());
                    targetDetailService.saveTargetDetailRealValue(targetId, laboratory.getLdlc(), Constant.TargetProject.LDL.getType());
                }
                //endregion
            }
        }
    }

    private static float decimalFormat(Double d) {
        float floatValue = d.floatValue();
        DecimalFormat decimalFormat = new DecimalFormat("0.0");
        String s = decimalFormat.format(floatValue);
        return Float.parseFloat(s);
    }

}
